﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;

namespace Bingo.Lottery
{
    public partial class ucNumber : UserControl
    {
        #region Attributes

        private delegate void myDeleGateInitDataGridView();
        private delegate void myDeleGateSetCollectPanel(bool b);
        private delegate void myDeleGateSetProgresPanel(bool b, string s, int max);

        private string CollectURL = "";
        private int CollectParamStart = 0;
        private int CollectParamEnd = 0;
        private string CollectRegex = "";
        private long CollectDateStart = 0;
        private long CollectDateEnd = 0;
        private bool ForceUpdate = false;
        
        #endregion

        #region ucLotteryNumber

        public ucNumber()
        {
            InitializeComponent();
            this.statusStrip.BackColor = Bingo.AeroColor; 
            this.pCollect.BackColor = Color.FromArgb(5, 0, 0, 0);
            this.pProgress.BackColor = Color.FromArgb(5, 0, 0, 0);
            this.pInput.BackColor = Color.FromArgb(5, 0, 0, 0);
        }

        private void ucNumber_Load(object sender, EventArgs e)
        {
            InitDataGridView();
        }

        private void ucNumber_SizeChanged(object sender, EventArgs e)
        {
            this.picClose.Location = new Point(this.Width - this.picClose.Width - 10, 3);
            if (this.pCollect.Visible) this.pCollect.Location = new Point((this.Width - this.pCollect.Width) / 2, (this.Height - this.pCollect.Height) / 4);
            if (this.pProgress.Visible) this.pProgress.Location = new Point((this.Width - this.pProgress.Width) / 2, (this.Height - this.pProgress.Height) / 4);
            if (this.pInput.Visible) this.pInput.Location = new Point((this.Width - this.pInput.Width) / 2, (this.Height - this.pInput.Height) / 4);
        }

        #endregion

        #region Event

        #region Button

        #region Collect

        private void btnCollect_Click(object sender, EventArgs e)
        {
            if (((Bingo)this.ParentForm).myThread != null && ((Bingo)this.ParentForm).myThread.IsAlive)
            {
                MessageBox.Show("请等待其他操作完成");
                return;
            }

            SetCollectPanel(true);
        }

        private void btnCollectStart_Click(object sender, EventArgs e)
        {
            if (((Bingo)this.ParentForm).myThread != null && ((Bingo)this.ParentForm).myThread.IsAlive)
            {
                MessageBox.Show("请等待其他操作完成");
                return;
            }

            if (!getCollectParam()) return;
            saveCollectParam();

            ((Bingo)this.ParentForm).myThread = new Thread(new ThreadStart(ThreadCollect));
            ((Bingo)this.ParentForm).myThread.Start();
        }

        private void btnCollectCancel_Click(object sender, EventArgs e)
        {
            SetCollectPanel(false);
        }

        #endregion

        #region ADD&MOD&DEL

        private bool isAdd = true;

        private void btnAdd_Click(object sender, EventArgs e)
        {
            if (((Bingo)this.ParentForm).myThread != null && ((Bingo)this.ParentForm).myThread.IsAlive)
            {
                MessageBox.Show("请等待其他操作完成");
                return;
            }

            isAdd = true;
            SetInputPanel(true, null);
        }

        private void btnMod_Click(object sender, EventArgs e)
        {
            if (((Bingo)this.ParentForm).myThread != null && ((Bingo)this.ParentForm).myThread.IsAlive)
            {
                MessageBox.Show("请等待其他操作完成");
                return;
            }

            if (this.dgvList.SelectedRows.Count == 0)
            {
                MessageBox.Show("请选择要修改的记录");
                return;
            }
            if (this.dgvList.SelectedRows.Count != 1)
            {
                MessageBox.Show("每次只能修改一条记录");
                return;
            }

            isAdd = false;
            SetInputPanel(true, this.dgvList.SelectedRows[0]);
        }

        private void btnDel_Click(object sender, EventArgs e)
        {
            if (((Bingo)this.ParentForm).myThread != null && ((Bingo)this.ParentForm).myThread.IsAlive)
            {
                MessageBox.Show("请等待其他操作完成");
                return;
            } 
            
            if (this.dgvList.SelectedRows.Count == 0)
            {
                MessageBox.Show("请选择要删除的记录");
                return;
            }
            if (MessageBox.Show("确认要删除吗?", "系统提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.Cancel) return;

            SetProgressPanel(true, "", 0);
            List<string> pids=new List<string>();
            foreach(DataGridViewRow row in this.dgvList.SelectedRows)
            {
                pids.Add(row.Cells[0].Value.ToString());
            }
            int rval = BingoLib.Lottery.Issue.Delete(pids);
            if (rval <= 0)
            {
                MessageBox.Show("操作失败");
            }
            else
            {
                MessageBox.Show(string.Format("删除成功，共删除{0}条记录", rval));
                InitDataGridView();
            }
            SetProgressPanel(false, "", 0);
        }

        private void btnInputOK_Click(object sender, EventArgs e)
        {
            if (((Bingo)this.ParentForm).myThread != null && ((Bingo)this.ParentForm).myThread.IsAlive)
            {
                MessageBox.Show("请等待其他操作完成");
                return;
            }

            #region CheckInput

            if (this.tbInputPid.Text.Length == 0)
            {
                MessageBox.Show("请输入期号");
                return;
            }
            if (!(new Regex(@"\d{1,2}(;\d{1,2}){5}").IsMatch(this.tbInputRed.Text)))
            {
                MessageBox.Show("红色号码正确的总数应该为6，请检查");
                return;
            }
            foreach (string num in this.tbInputRed.Text.Split(';'))
            {
                if (!new Regex(@"([0][1-9])|([1-2][0-9])|(3[0-3])|[1-9]").IsMatch(num))
                {
                    MessageBox.Show("请输入正确的红色号码");
                    return;
                }
            }
            if (!(new Regex(@"(0[1-9])|(1[0-6])|[1-9]").IsMatch(this.tbInputBlue.Text)))
            {
                MessageBox.Show("请输入正确的蓝色号码");
                return;
            }

            #endregion

            #region DataBase

            BingoLib.OpaqueCommand.ShowOpaqueLayer(this.pInput, 125, true, null);

            BingoLib.StructLottery Lottery=new BingoLib.StructLottery();
            Lottery.pid = this.tbInputPid.Text;

            if (isAdd)
            {
                switch (BingoLib.Lottery.Issue.Add(Lottery, false))
                {
                    case -2:
                        MessageBox.Show("数据已存在");
                        break;
                    case 1:
                        MessageBox.Show("添加成功");
                        break;
                    default:
                        MessageBox.Show("操作失败");
                        break;
                }
            }
            else
            {
                if (BingoLib.Lottery.Issue.Add(Lottery, false) == 1)
                {
                    MessageBox.Show("修改成功");
                }
                else
                {
                    MessageBox.Show("操作失败");
                }
            }

            InitDataGridView();
            BingoLib.OpaqueCommand.ShowOpaqueLayer(this.pInput, 125, false, null);

            #endregion

            SetInputPanel(false, null);
        }

        private void btnInputCancel_Click(object sender, EventArgs e)
        {
            this.pInput.Visible = false;
        }

        #endregion

        #endregion

        #region PictureBox

        private void picClose_MouseEnter(object sender, EventArgs e)
        {
            this.picClose.Image = Properties.Resources.close01;
        }

        private void picClose_MouseLeave(object sender, EventArgs e)
        {
            this.picClose.Image = Properties.Resources.close02;
        }

        private void picClose_Click(object sender, EventArgs e)
        {
            if (((Bingo)this.ParentForm).myThread != null && ((Bingo)this.ParentForm).myThread.IsAlive)
            {
                if (MessageBox.Show("正在进行操作，确定要退出吗？", "系统提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.Cancel)
                {
                    return;
                }
                ((Bingo)this.ParentForm).myThread.Abort();
            }
            this.Dispose();            
        }

        #endregion

        #region DataGridView

        private void dgvList_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
        {
            this.tsslMsg.Text = string.Format("数据总计：{0}", this.dgvList.RowCount);
        }

        private void dgvList_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex == -1) return;
            this.tsslPosition.Text = string.Format("      行 {0}      列 {1}", e.RowIndex + 1, e.ColumnIndex + 1);
        }

        #endregion

        #endregion

        #region Thread

        private void ThreadCollect()
        {
            try
            {
                SetCollectPanel(false);

                string url = "";
                string ref_url = "";
                Regex regex = new Regex(CollectRegex);
                BingoLib.StructLottery Lottery = new BingoLib.StructLottery();
                int index = 0;
                int skip = 0, failed = 0;

                SetProgressPanel(true, string.Format("已采集数量：{0}", index), 0);
                for (int i = CollectParamStart; i <= CollectParamEnd; i++)
                {
                    ref_url = url;
                    url = string.Format(CollectURL, i.ToString(), this.dtpCollectStart.Value.ToString("yyyy-MM-dd"), this.dtpCollectEnd.Value.ToString("yyyy-MM-dd"));
                    string HtmlData = "";
                    if (!BingoLib.Collect.getHtml(url, ref_url, Encoding.UTF8, out HtmlData)) continue;
                    HtmlData = Regex.Replace(HtmlData, @"\s", "", RegexOptions.IgnoreCase);

                    MatchCollection mc = regex.Matches(HtmlData);

                    if (mc.Count == 0) break;

                    foreach (Match mt in mc)
                    {
                        if (long.Parse(mt.Groups["date"].Value.Replace("-", "").Replace("/", "")) > CollectDateEnd) continue;
                        if (long.Parse(mt.Groups["date"].Value.Replace("-", "").Replace("/", "")) < CollectDateStart)
                        {
                            SetProgressPanel(false, "", 0);
                            InitDataGridView();
                            return;
                        }

                        Lottery.pid = mt.Groups["pid"].Value;
                        Lottery.rundate = mt.Groups["date"].Value;
                        Lottery.red = mt.Groups["r1"].Value + ";" + mt.Groups["r2"].Value + ";" + mt.Groups["r3"].Value + ";" + mt.Groups["r4"].Value + ";" + mt.Groups["r5"].Value;
                        Lottery.blue = mt.Groups["b1"].Value + ";" + mt.Groups["b2"].Value;

                        #region DataBase

                        switch (BingoLib.Lottery.Issue.Add(Lottery, this.ForceUpdate))
                        {
                            case -2:
                                skip++;
                                break;
                            case 1:
                                break;
                            default:
                                failed++;
                                break;
                        }

                        #endregion

                        index++;
                        SetProgressPanel(true, string.Format("第{0}期采集完成；已采集数量：{1}，其中跳过：{2},失败：{3}", Lottery.pid, index, skip, failed), 0);
                    }
                }

                SetProgressPanel(false, "", 0);
                InitDataGridView();
            }
            catch (ThreadAbortException)
            {
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        #endregion

        #region Method

        private void InitDataGridView()
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new myDeleGateInitDataGridView(InitDataGridView));
            }
            else
            {
                DataTable dt = BingoLib.Lottery.Issue.getAll();
                this.dgvList.AutoGenerateColumns = false;
                this.dgvList.Columns[0].DataPropertyName = "pid";
                this.dgvList.Columns[1].DataPropertyName = "rundate";
                this.dgvList.Columns[2].DataPropertyName = "red";
                this.dgvList.Columns[3].DataPropertyName = "blue";
                this.dgvList.DataSource = dt;
            }
        }

        private bool getCollectParam()
        {
            if (this.tbCollectURL.Text.Length == 0)
            {
                MessageBox.Show("请填写完整的网址");
                return false;
            }
            Regex regex = new Regex(@"^\d+$");
            if(!regex.IsMatch(this.tbCollectParamStart.Text)||!regex.IsMatch(this.tbCollectParamEnd.Text))
            {
                MessageBox.Show("网址参数必须为数字");
                return false;
            }
            if (this.tbCollectRegex.Text.Length == 0)
            {
                MessageBox.Show("请输入正则表达式");
                return false;
            }

            this.CollectURL = this.tbCollectURL.Text;
            this.CollectParamStart = int.Parse(this.tbCollectParamStart.Text);
            this.CollectParamEnd = int.Parse(this.tbCollectParamEnd.Text);
            this.CollectRegex = this.tbCollectRegex.Text;
            this.CollectDateStart = long.Parse(this.dtpCollectStart.Value.ToString("yyyyMMdd"));
            this.CollectDateEnd = long.Parse(this.dtpCollectEnd.Value.ToString("yyyyMMdd"));
            this.ForceUpdate = this.cbForce.Checked;

            return true;
        }

        private void setCollectParam()
        {
            this.tbCollectURL.Text = BingoLib.Lottery.Setting.get("CollectURL");
            string[] paras = BingoLib.Lottery.Setting.get("CollectParam").Split('|');
            this.tbCollectParamStart.Text = paras.Length > 0 ? paras[0] : "1";
            this.tbCollectParamEnd.Text = paras.Length > 1 ? paras[1] : "1";
            this.tbCollectRegex.Text = BingoLib.Lottery.Setting.get("CollectRegex");
        }

        private void saveCollectParam()
        {
            BingoLib.Lottery.Setting.update("CollectURL", this.CollectURL);
            BingoLib.Lottery.Setting.update("CollectParam", this.CollectParamStart + "|" + this.CollectParamEnd);
            BingoLib.Lottery.Setting.update("CollectRegex", this.CollectRegex);
        }

        private void SetCollectPanel(bool b)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new myDeleGateSetCollectPanel(SetCollectPanel), new object[] { b });
            }
            else
            {
                if (b) setCollectParam();
                this.pCollect.Visible = b;
            }
        }

        private void SetProgressPanel(bool b, string s, int max)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new myDeleGateSetProgresPanel(SetProgressPanel), new object[] { b, s, max });
            }
            else
            {
                this.pProgress.Visible = b;
                if (max == 0)
                {
                    this.pbProgress.Style = ProgressBarStyle.Marquee;
                }
                else
                {
                    this.pbProgress.Style = ProgressBarStyle.Blocks;
                    this.pbProgress.Maximum = max;
                }
                this.lblMsg.Text = s;
                this.lblMsg.Location = new Point((this.pProgress.Width - this.lblMsg.Width) / 2, this.lblMsg.Location.Y);
            }
        }

        private void SetInputPanel(bool b, DataGridViewRow row)
        {
            if (row != null)
            {
                this.tbInputPid.Text = row.Cells[0].Value.ToString();
                this.dtpInputRunDate.Value = DateTime.Parse(row.Cells[1].Value.ToString());
                this.tbInputRed.Text = row.Cells[2].Value.ToString();
                this.tbInputBlue.Text = row.Cells[3].Value.ToString();
            }
            this.pInput.Visible = b;
        }

        #endregion
    }
}
